package com.bourse.core.ibatisHandler;

import java.sql.Date;
import java.sql.SQLException;
import java.sql.Types;

import org.apache.log4j.Logger;
import org.joda.time.DateMidnight;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import com.ibatis.sqlmap.client.extensions.ParameterSetter;
import com.ibatis.sqlmap.client.extensions.ResultGetter;
import com.ibatis.sqlmap.client.extensions.TypeHandlerCallback;

/**
 * Class to parse and format {@link DateMidnight} objects.
 */
public class DateMidnightHandlerCallback implements TypeHandlerCallback {

	/** The Log4j logger for the class. */
	private static final Logger LOGGER = Logger.getLogger(DateMidnightHandlerCallback.class);

	/**
	 * The formatter to handle dates to and from the database.<br/>
	 * According to the javadoc of {@link DateTimeFormat}, the {@link DateTimeFormatter} returned by
	 * {@link DateTimeFormat#forPattern(String)} is thread safe, so we can use a static instance.
	 */
	private final DateTimeFormatter DB_DATE_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd");

	/**
	 * @see TypeHandlerCallback#getResult(ResultGetter)
	 */
	public Object getResult(ResultGetter getter) throws SQLException {
		DateMidnight dateMidnight = null;
		Date date = getter.getDate();
		if (!getter.wasNull()) {
			// Parse the date as returned by the database.
			dateMidnight = new DateMidnight(date);
		}
		return dateMidnight;
	}

	/**
	 * @see TypeHandlerCallback#setParameter(ParameterSetter, Object)
	 */
	public void setParameter(ParameterSetter setter, Object obj) throws SQLException {
		if (obj == null) {
			setter.setNull(Types.DATE);
		} else if (obj instanceof DateMidnight) {
			DateMidnight dateMidnight = (DateMidnight) obj;
			setter.setDate(new Date(dateMidnight.getMillis()));
		} else {
			throw new IllegalArgumentException("Unexpected object type : " + obj.getClass());
		}
	}

	/**
	 * @see TypeHandlerCallback#valueOf(String)
	 */
	public Object valueOf(String string) {

		// We should never return null unless null was passed in. See TypeHandler#valueOf().
		if (string == null) {
			return null;
		}

		Object dateMidnight = null;
		try {
			// Try parsing as a date + time + millis.
			dateMidnight = DB_DATE_FORMATTER.parseDateTime(string).toDateMidnight();
		} catch (IllegalArgumentException e) {
			LOGGER.warn("Unexpected date format in " + DateMidnightHandlerCallback.class.getSimpleName() + " for \'"
					+ string + "\'");
		}
		if (dateMidnight == null) {
			return string;
		}
		return dateMidnight;
	}
}
